const { pause } = require("../utils/interaction_tool");
const { warn, error, info, success, getPrint } = require("../utils/log_tool");
const {
    formatTimeInMillisec,
    formatDate,
    convert,
} = require("../utils/transform_tool");
const { BaseCommand } = require("./base");
const { formatData } = require("./share_data");

class ScheduleCommand extends BaseCommand {
    async execute() {
        await new Promise(async (resolve, _reject) => {
            const data = this.selfData;
            let commandCfgs = data.commands;
            /** 是否阻塞 */
            const blocked = data.blocked;
            // 特殊处理字符的情况
            if (typeof commandCfgs === "string") {
                commandCfgs = formatData(commandCfgs);
            }
            const now = Date.now();
            let timeout;
            let timeout_date = null;
            switch (data.schedule_type) {
                case "delay": {
                    timeout = convert(data.value, "millisecond");
                    break;
                }
                case "date": {
                    const date = new Date(data.value);
                    timeout = date - now;
                    timeout_date = date;
                    break;
                }
                default: {
                    throw `不支持的计划任务类型 ${data.schedule_type}`;
                    return;
                }
            }
            let asyncId;
            if (!timeout_date) {
                timeout_date = new Date(now + timeout);
            }
            if (Number.isNaN(timeout_date)) {
                throw `日期格式不正确 ${data.value}`;
                return;
            }
            const willConfirm = timeout <= 0 && !data.force;
            const timer = setTimeout(async () => {
                if (willConfirm) {
                    await pause(`需要确认后才可执行任务[${asyncId}]!`);
                }
                info("");
                warn(`开始执行计划任务[${asyncId}]`);
                await this.exec(commandCfgs, this.depth + 1);
                if (blocked) {
                    resolve();
                }
            }, timeout);
            asyncId =
                timer[
                    Object.getOwnPropertySymbols(timer).find(
                        (v) => v.description === "asyncId",
                    )
                ];
            info("");
            if (timeout <= 0) {
                warn(
                    `将在${formatDate(timeout_date)} 时间已过期${formatTimeInMillisec(-timeout)}, 立刻执行计划任务[${asyncId}]`,
                );
            } else {
                warn(
                    `将在${formatDate(timeout_date)} (${formatTimeInMillisec(timeout)}后)执行计划任务[${asyncId}]`,
                );
            }
            if (!blocked) {
                resolve();
            }
        });
    }

    getRequiredParams() {
        return ["schedule_type", "value"];
    }
}

module.exports = {
    ScheduleCommand,
};
